#include "utilities.h"

void *terminalCommands(void *ptr)
{
	int ind;
	map<int,writeListData>::iterator it;
	fd_set rfds;
    struct timeval tv, time1, starttime;
	gettimeofday(&starttime,NULL);
    int retval;
	FD_ZERO(&rfds);
    FD_SET(fileno(stdin), &rfds);
    tv.tv_sec = initMap["AutoShutdown"].asDouble;
    tv.tv_usec = 0;
	cout<<"servant:"<<port_recieve<<"> ";
    fflush(stdout);
	retval = select(1, &rfds, NULL, NULL, &tv);
	while(1) 
	{	
		ind = 0;
		if(retval==0)
		{
			break;
		}
		if(signalIntFlag)
		{
			signalIntFlag = 0;
			gettimeofday(&time1,NULL);
			tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
			tv.tv_usec = 0;
			retval = select(1, &rfds, NULL, NULL, &tv);
		}
		fflush(stdout);
		if (FD_ISSET(fileno(stdin), &rfds))
		{ 
			cin.getline(input_line, 512);
			if(strcmp(input_line, "") == 0)
			{
				cout<<"Bad Command"<<endl;
				fflush(stdin);
				continue;
			}
			char *str;
			if(printFlag==1)
			{
				cout<<" ----- "<<input_line<<endl;
			}
			str = strtok(input_line, " ");
			char command[20];
			char type[20];
			int ttl;
			
			strcpy(command, str);
			ind++;
			if(strcmp(command, "shutdown") == 0)
			{
				tv.tv_sec = 0;
				tv.tv_usec = 0;
				retval = select(1, &rfds, NULL, NULL, &tv);
				notifyFlag = true;
				if(printFlag==1)
				{
					cout<<"Shutdown has been initiated"<<endl;
				}
				uint8_t notifyType = 1;
				char obj[256];
				strcpy(obj, "NTFY");
				msg_header notify_req;
				createMsgHdrStr(&notify_req,0xF7,1,obj,node_instance_id,sizeof(uint8_t));
				
				listBuffStruct lbtemp;
				memset(lbtemp.listBuff, '\0', 27+sizeof(uint8_t));
				fillMsgHdrBuffer(notify_req, lbtemp.listBuff);
				memcpy(&(lbtemp.listBuff[27]), &notifyType, sizeof(uint8_t));
				lbtemp.datalength = 27 + sizeof(uint8_t);
				lbtemp.logtype = 1;
				//Put it on every write queue
				pthread_mutex_lock(&writeMapMutex);
				if(printFlag==1)
				{
					cout<<"Size - "<<writeMap.size()<<endl;
				}
				for(it=writeMap.begin(); it!=writeMap.end(); it++)
				{
					lbtemp.portNumber = (*it).first;
					writeListData listDataStr = writeMap[(*it).first];
					listDataStr.response.push_back(lbtemp);
					writeMap[(*it).first] = listDataStr;
					pthread_mutex_lock(&notifyLock);
					notifyCount++;
					if(printFlag==1)
					{
						cout<<"Notify Count set - "<<notifyCount<<endl;
					}
					pthread_mutex_unlock(&notifyLock);
				}
				pthread_mutex_unlock(&writeMapMutex);
				pthread_mutex_lock(&notifyLock);
				if((notifyCount == 0 || writeMap.size() == 0) && notifyFlag)
				{
					if(printFlag==1)
					{
						cout<<"Ending"<<endl;
					}
					pthread_mutex_unlock(&notifyLock);
					serverShutdown = true;
					dieChild = true;
					if(printFlag==1)
					{
						cout<<statusFile<<endl;
					}
					close(globalAcceptSock);
					pthread_exit(NULL);
				}
				else
				{
					pthread_mutex_unlock(&notifyLock);
				}
				fflush(stdout);
				tv.tv_sec = 0;
				tv.tv_usec = 0;	
				retval = select(1, &rfds, NULL, NULL, &tv);
			}
			else if(strcmp(command, "status") == 0)
			{
				while(str != NULL)
				{
					str = strtok(NULL, " ");
					if(str != NULL)
					{
						if(ind == 1)
						{
							strcpy(type, str);
						}
						if(ind == 2)
						{
							ttl = atoi(str);
						}
						if(ind == 3)
						{
							memcpy(statusFile, str, strlen(str));
						}
						ind++;
					}
				}
				if(ind != 4)
				{
					cout<<"Number of arguments do not match in command Line"<<endl;
					cout<<"servant:"<<port_recieve<<"> ";
					fflush(stdout);
					gettimeofday(&time1,NULL);
					tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
					tv.tv_usec = 0;
					retval = select(1, &rfds, NULL, NULL, &tv);
					continue;
				}
				if(ttl != 0)
				{
					//Get response from other neighbors
					status_msg statMsg;
					if(strcmp(type, "neighbors") == 0)
					{
						statMsg.statustype = 0x01;
					}
					else
					{
						statMsg.statustype = 0x02;
					}
					char obj[256];
					strcpy(obj, "STRQ");
					if(printFlag==1)
					{
						cout<<statusFile<<endl;
					}
					struct timeval t1;
					gettimeofday(&t1,NULL);
					globalStatusTime = (double)(t1.tv_sec * 1000 + (double)t1.tv_usec/1000);
					msg_header statusReq;
					createMsgHdrStr(&statusReq,0xAC,ttl,obj,node_instance_id,sizeof(status_msg));
					statusSTR sent;
					memcpy(sent.uoid,statusReq.uoid,20);
					statusResponseList.push_back(sent);
					listBuffStruct lbtemp;
					lbtemp.logtype = 1;
					memset(lbtemp.listBuff, '\0', 27+sizeof(status_msg));
					fillMsgHdrBuffer(statusReq, lbtemp.listBuff);
					memcpy(&(lbtemp.listBuff[27]), &statMsg, sizeof(status_msg));
					lbtemp.datalength = 27 + sizeof(status_msg);
					pthread_mutex_lock(&writeMapMutex);
					for(it=writeMap.begin(); it!=writeMap.end(); it++)
					{
						lbtemp.portNumber = (*it).first;
						writeListData listDataStr = writeMap[(*it).first];
						listDataStr.response.push_back(lbtemp);
						writeMap[(*it).first] = listDataStr;
					}
					pthread_mutex_unlock(&writeMapMutex);
					cout<<"Processing ..."<<endl;
					while(!dieChild)
					{
						if(globalStatusTime == 0 || globalStatusTime == -1)
						{
							break;
						}
						usleep(10);
					}
					if(signalIntFlag!=1)
					{
						cout<<"servant:"<<port_recieve<<"> ";
					}
				}
				else
				{
					//Just note down the neighbors of the current node onto a file
					FILE *file;
					char path[256];
					memset(path, '\0', 256);
					strcpy(path, statusFile);
					file = fopen(path, "w");
					if(file == NULL)
					{
						if(printFlag==1)
						{
						cout<<"Problem in opening the file"<<endl;
						}
						exit(0);
					}
					char dataStatus[256];
					memset(dataStatus, '\0', 256);
					strcpy(dataStatus, "V -t * -v 1.0a5\n");
					fputs(dataStatus, file);
					memset(dataStatus, '\0', 256);
					sprintf(dataStatus, "n -t * -s %d -c red -i black\n", port_recieve);
					fputs(dataStatus, file);
					pthread_mutex_lock(&writeMapMutex);
					for(it=writeMap.begin(); it!=writeMap.end(); it++)
					{
						memset(dataStatus, '\0', 256);
						sprintf(dataStatus, "n -t * -s %d -c red -i black\n", (*it).first);
						fputs(dataStatus, file);
					}
					for(it=writeMap.begin(); it!=writeMap.end(); it++)
					{
						memset(dataStatus, '\0', 256);
						sprintf(dataStatus, "l -t * -s %d -d %d -c blue\n", port_recieve, (*it).first);
						fputs(dataStatus, file);
					}
					pthread_mutex_unlock(&writeMapMutex);
					memset(statusFile, '\0', 128);
					fclose(file);
					cout<<"servant:"<<port_recieve<<"> ";
				}
				fflush(stdout);
				gettimeofday(&time1,NULL);
				tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
				tv.tv_usec = 0;
				retval = select(1, &rfds, NULL, NULL, &tv);
			}
			else
			{
					cout<<"BAD COMMAND"<<endl;
					cout<<"servant:"<<port_recieve<<"> ";
					fflush(stdout);
					gettimeofday(&time1,NULL);
					tv.tv_sec = initMap["AutoShutdown"].asDouble-(time1.tv_sec-starttime.tv_sec);
					tv.tv_usec = 0;
					retval = select(1, &rfds, NULL, NULL, &tv);
			}
		}	
		usleep(1);
	}
	if(printFlag==1)
	{
		cout<<"tmc ends"<<endl;
	}
	fflush(stdout);
	pthread_exit(NULL);
}
